#include "dicom/hippa_log.h"
#include "dicom/dmv_db.h"
#include <json/json.h>
#include <gwbase/base/string_util.h>
#include <gwbase/base/mutex.h>

namespace dicom {

static std::string GetFullPath(DmvDBPtr& db, const std::string& dir_id,
                               const std::string& filename) {
  std::string dpath;
  db->GetDirPath(dir_id, &dpath);
  return path::Join(dpath, filename);
}

static const char* GetOpCodeName(OperationCode code) {
  switch (code) {
    case OP_LOGIN:
      return "LOGIN";
    case OP_LOGOUT:
      return "LOGOUT";
    case OP_UPLOAD_FILE:
      return "UPLOAD_FILE";
    case OP_DELETE_FILE:
      return "DEL_FILE";
    case OP_DOWNLOAD_FILE:
      return "DOWNLOAD_FILE";
    case OP_CREATE_DIR:
      return "CREATE_DIR";
    case OP_DELETE_DIR:
      return "DELETE_DIR";
    case OP_LIST_FILE:
      return "LIST_DIR";
    case OP_STAT_FILE:
      return "STAT_FILE";
    case OP_RENAME_FILE:
      return "RENAME_FILE";
    case OP_RENAME_DIR:
      return "RENAME_DIR";
    case OP_NONE:
      return "NONE";
  }
  return "";
}

static dicom::LogSink* s_sink = NULL;
static dicom::Mutex s_mu;

void InitHippaLog(const DicomConf* conf) {
  LockGuard g(s_mu);
  if (s_sink == NULL) {
    s_sink = CreateRollingFileLogSink(conf->GetLogDir(), "hippa_op");
  }
}

void LogHippaOperation(OperationCode code, DmvDBPtr& db,
                       const CredentialPtr& cred, const std::string dir_id,
                       const std::string name, const std::string new_dir_id,
                       const std::string new_name) {
  std::string fullname = GetFullPath(db, dir_id, name);
  std::string new_fullname = "";
  if (!new_dir_id.empty()) {
    new_fullname = GetFullPath(db, new_dir_id, new_name);
  }

  Json::Value v;
  v["user"] = cred->email;
  if (!cred->ukey_id.empty()) {
    v["ukey_id"] = cred->ukey_id;
  }

  v["op"] = GetOpCodeName(code);
  if (code != OP_LOGIN && code != OP_LOGOUT) {
    v["name"] = fullname.c_str();
  }
  if (code == OP_RENAME_DIR || code == OP_RENAME_FILE) {
    v["new_name"] = new_fullname;
  }
  v["datetime"] = Timestamp::Now().ToISO8601();

  v.toStyledString();
  std::string msg = v.toStyledString();
  assert(s_sink != NULL);
  s_sink->WriteLog(msg.c_str(), msg.size());
  s_sink->Flush();

  // LOG_INFO << "HIPP OPERATION LOG: \n" << v.toStyledString();
}

void LogHippaAccountOperation(OperationCode code, const std::string& email,
                              const std::string& ukey_id) {
  Json::Value v;
  v["user"] = email;
  if (!ukey_id.empty()) {
    v["ukey_id"] = ukey_id;
  }
  v["op"] = GetOpCodeName(code);
  v["datetime"] = Timestamp::Now().ToISO8601();
  v.toStyledString();
  std::string msg = v.toStyledString();
  assert(s_sink != NULL);
  s_sink->WriteLog(msg.c_str(), msg.size());
  s_sink->Flush();
}
}
